/*
 * Copyright (C) 2012  Forklabs Daniel Léonard
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package ca.forklabs.soap.axis.client.util;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.Locale;
import ca.gc.dfo.wds.BoundaryDate;
import ca.gc.dfo.wds.BoundaryDepth;
import ca.gc.dfo.wds.BoundarySpatial;
import ca.gc.dfo.wds.Data;
import ca.gc.dfo.wds.Metadata;
import ca.gc.dfo.wds.RealBoundary;
import ca.gc.dfo.wds.ResultSet;
import ca.gc.dfo.wds.SpatialCoordinate;
import ca.gc.dfo.wds.Status;
import ca.gc.dfo.wds.StringBoundary;
import ca.gc.shc.ws.DataSpine;
import ca.gc.shc.ws.ResultSpine;

/**
 * Class {@code WDSInspector} is a rudimentary set of methods to inspect
 * {@link ResultSet}s, {@link Data} and other WDS objects.
 *
 * Where text is necessary, the English language has been used.
 *
 * @author   <a href="mailto:forklabs at gmail.com?subject=ca.forklabs.soap.axis.client.util.WDSInspector">Daniel Léonard</a>
 * @version $Revision$
 */
@SuppressWarnings({ "boxing", "nls" })
public class WDSInspector {

//---------------------------
// Class variables
//---------------------------

   /** The end of line character. */
   protected static final String EOL = AccessController.doPrivileged(new PrivilegedAction<String>() {
      @Override
      public String run() {
         String eol = System.getProperty("line.separator");
         return eol;
         }
      });


//---------------------------
// Constructor
//---------------------------

   /**
    * Constructor.
    */
   protected WDSInspector() {
   // nothing
      }


//---------------------------
// Inspection class methods
//---------------------------


   /**
    * Builds up a string to inspect the values of a {@code BoundaryDate}.
    * @param   dates   the boundary dates.
    * @return   a string.
    */
   public static String inspectBoundaryDate(BoundaryDate dates) {
      String pattern = "BoundaryDate[from:\"{0}\", to:\"{1}\"]";
      String min_date = dates.getMin();
      String max_date = dates.getMax();
      String text = MessageFormat.format(pattern, min_date, max_date);
      return text;
      }

   /**
    * Builds up a string to inspect the values of a {@code BoundaryDepth}.
    * @param   depths   the boundary depths.
    * @return   a string.
    */
   public static String inspectBoundaryDepth(BoundaryDepth depths) {
      Locale old_locale = Locale.getDefault();
      Locale.setDefault(Locale.ENGLISH);

      String text = "";
      try {
         String pattern = "BoundaryDepth[from:\"{0,number,0.000}\", to:\"{1,number,0.000}\"]";
         double min_depth = depths.getMin();
         double max_depth = depths.getMax();
         text = MessageFormat.format(pattern, min_depth, max_depth);
         }
      finally {
         Locale.setDefault(old_locale);
         }

      return text;
      }

   /**
    * Builds up a string to inspect the values of a {@code BoundarySpatial}.
    * @param   boundaries   the boundaries.
    * @return   a string.
    */
   public static String inspectBoundarySpatial(BoundarySpatial boundaries) {
      Locale old_locale = Locale.getDefault();
      Locale.setDefault(Locale.ENGLISH);

      String text = "";
      try {
         String pattern = "BoundarySpatial[from:\"{0,number,0.000} x {1,number,0.000}\", to:\"{2,number,0.000} x {3,number,0.000}\"]";
         RealBoundary latitudes = boundaries.getLatitude();
         double min_lat = latitudes.getMin();
         double max_lat = latitudes.getMax();

         RealBoundary longitudes = boundaries.getLongitude();
         double min_long = longitudes.getMin();
         double max_long = longitudes.getMax();

         text = MessageFormat.format(pattern, min_lat, min_long, max_lat, max_long);
         }
      finally {
         Locale.setDefault(old_locale);
         }

      return text;
      }

   /**
    * Builds up a string to inspect one {@code SpatialCoordinate}.
    * @param   coordinate   the coordinates.
    * @return   a string.
    */
   public static String inspectSpatialCoordinate(SpatialCoordinate coordinate) {
      Locale old_locale = Locale.getDefault();
      Locale.setDefault(Locale.ENGLISH);

      String text = "";
      try {
         String pattern = "SpatialCoordinate[\"{0,number,0.000} x {1,number,0.000}\"]";
         double latitude = coordinate.getLatitude();
         double longitude = coordinate.getLongitude();
         text = MessageFormat.format(pattern, latitude, longitude);
         }
      finally {
         Locale.setDefault(old_locale);
         }

      return text;
      }

   /**
    * Builds up a string to inspect many {@code SpatialCoordinate}s.
    * @param   coordinates   the coordinates.
    * @return   a string.
    */
   public static String inspectSpatialCoordinates(SpatialCoordinate[] coordinates) {
      String text = "* There are " + coordinates.length + " spatial coordinates" + EOL;
      for (SpatialCoordinate coordinate : coordinates) {
         text += "** " + inspectSpatialCoordinate(coordinate) + EOL;
         }
      return text;
      }

   /**
    * Builds up a string to inspect one {@code Metadata}.
    * @param   metadata   the metadata.
    * @return   a string.
    */
   public static String inspectMetadata(Metadata metadata) {
      String pattern = "Metadata[name:\"{0}\", value:\"{1}\"]";
      String name = metadata.getName();
      String value = metadata.getValue();
      String text = MessageFormat.format(pattern, name, value);
      return text;
      }

   /**
    * Builds up a string to inspect many {@code Metadata}s.
    * @param   metadatas   the metadatas.
    * @return   a string.
    */
   public static String inspectMetadatas(Metadata[] metadatas) {
      String text = "* There are " + metadatas.length + " metadatas" + EOL;
      for (Metadata metadata : metadatas) {
         text += "** " + inspectMetadata(metadata) + EOL;
         }
      return text;
      }

   /**
    * Builds up a string to inspect the values of a {@code Data}.
    * @param   data   the data.
    * @return   a string.
    */
   public static String inspectData(Data data) {
      String text = "";
      text += "* Value = " + data.getValue() + EOL;
      text += "* " + inspectBoundaryDate(data.getBoundaryDate()) + EOL;
      text += "* " + inspectBoundaryDepth(data.getBoundaryDepth()) + EOL;
      text += inspectSpatialCoordinates(data.getSpatialCoordinates());
      text += inspectMetadatas(data.getMetadata());
      return text;
      }

   /**
    * Builds up a string to inspect many {@code Data}s.
    * @param   datas   the datas.
    * @return   a string.
    */
   public static String inspectDatas(Data[] datas) {
      String text = "* There are " + datas.length + " datas" + EOL;
      for (Data data : datas) {
         text += inspectData(data);
         }
      return text;
      }

   /**
    * Builds up a string to inspect the values of a {@code Status}.
    * @param   status   the status.
    * @return   a string.
    */
   public static String inspectStatus(Status status) {
      String pattern = "Status[code:\"{0}\", message:\"{1}\"]";
      String code = status.getStatus();
      String message = status.getMessage();
      String text = MessageFormat.format(pattern, code, message);
      return text;
      }

   /**
    * Builds up a string to inspect the values of a {@code StringBoundary}.
    * @param   strings   the boundary strings.
    * @return   a string.
    */
   public static String inspectStringBoundary(StringBoundary strings) {
      String pattern = "StringBoundary[min:\"{0}\", max:\"{1}\"]";
      String min = strings.getMin();
      String max = strings.getMax();
      String text = MessageFormat.format(pattern, min, max);
      return text;
      }

   /**
    * Builds up a string to inspect the values of a {@code ResultSet}.
    * @param   results   the results.
    * @return   a string.
    */
   public static String inspectResultSet(ResultSet results) {
      String text = "";
      text += "* " + inspectStatus(results.getStatus()) + EOL;
      text += "* " + inspectStringBoundary(results.getBoundaryValue()) + EOL;
      text += "* " + inspectBoundaryDate(results.getBoundaryDate()) + EOL;
      text += "* " + inspectBoundaryDepth(results.getBoundaryDepth()) + EOL;
      text += "* " + inspectBoundarySpatial(results.getBoundarySpatial()) + EOL;
      text += inspectMetadatas(results.getMetadata());
      text += inspectDatas(results.getData());
      return text;
      }

   /**
    * Builds up a string to inspect the values of a {@code DataSpine}.
    * @param   data   the data.
    * @return   a string.
    */
   public static String inspectDataSpine(DataSpine data) {
      Locale old_locale = Locale.getDefault();
      Locale.setDefault(Locale.ENGLISH);

      String text = "";
      try {
         text += "* Value = " + MessageFormat.format("{0,number,0.000}", data.getValue()) + EOL;
         text += "* Type = " + data.getType() + EOL;
         text += "* Date = " + data.getDate() + EOL;
         text += "* " + inspectSpatialCoordinate(data.getSpatialCoordinate()) + EOL;
         text += inspectMetadatas(data.getMetadata());
         }
      finally {
         Locale.setDefault(old_locale);
         }


      return text;
      }

   /**
    * Builds up a string to inspect many {@code DataSpine}s.
    * @param   datas   the datas.
    * @return   a string.
    */
   public static String inspectDataSpines(DataSpine[] datas) {
      String text = "* There are " + datas.length + " datas" + EOL;
      for (DataSpine data : datas) {
         text += inspectDataSpine(data);
         }
      return text;
      }

   /**
    * Builds up a string to inspect the values of a {@code ResultSpine}.
    * @param   results   the results.
    * @return   a string.
    */
   public static String inspectResultSpine(ResultSpine results) {
      String text = "";
      text += "* " + inspectStatus(results.getStatus()) + EOL;
      text += inspectMetadatas(results.getMetadata());
      text += inspectDataSpines(results.getData());
      return text;
      }

   }
